/*
COPYRIGHT (C) 2008 EPISERVER AB

THIS FILE IS PART OF WIKIX.
WIKIX IS FREE SOFTWARE: YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT UNDER THE TERMS OF THE GNU LESSER GENERAL PUBLIC LICENSE VERSION v2.1 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION.

WIKIX IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU LESSER GENERAL PUBLIC LICENSE FOR MORE DETAILS.
YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC LICENSE ALONG WITH WIKIX. IF NOT, SEE <HTTP://WWW.GNU.ORG/LICENSES/>.
*/

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Text.RegularExpressions;
using EPiServer.Web;
using EPiServer.Core;
using EPiServer;
using EPiServer.Web.Hosting;
using EPiServer.Research.Wiki;

namespace EPiServer.Research.Wiki.Core
{
    /// <summary>
    /// Used to parse content for Wiki syntax
    /// </summary>
    public class WikiParser
    {
        private WikiSyntax ws;
        private PageReference pr;

        public string Parse(string s, PageReference pr)
        {
            StringBuilder sb = new StringBuilder(s);
            Parse(sb,pr);
            return sb.ToString();
        }

        public void Parse(StringBuilder txt, PageReference pr)
        {
            //Fire off master regex
            MatchCollection mcol = ws.Matches(txt.ToString());
            //Traverse matches from reverse
            for (int i = (mcol.Count - 1); i >= 0; i--)
            {
                //Iterate backwards to replace
                Match m = mcol[i];
                string replacement = null;
                string title=HttpUtility.HtmlEncode(m.Groups["title"].Value);

                if (!string.IsNullOrEmpty(m.Groups["image"].Value))
                {
                    //Image link
                    PageData pd = WikiManager.Instance.GetWikiArticle(pr);
                    UnifiedDirectory ud=pd.GetPageDirectory(false);
                    if (ud != null)
                    {
                        string style = "";
                        if (!string.IsNullOrEmpty(m.Groups["imageloc"].Value))
                        {
                            style = "float:" + m.Groups["imageloc"].Value;
                            if (m.Groups["imageloc"].Value == "center")
                            {
                                style = "float: middle";
                            }
                            style += "; padding: 4px 4px 4px 4px; ";
                        }
                        //TODO: Consider using ArticleViewImage css class
                        string alt = "";
                        if (!string.IsNullOrEmpty(m.Groups["imagealt"].Value)) alt = m.Groups["imagealt"].Value;
                        replacement = string.Format("<img src=\"{0}\"/ style=\"{1}\" alt=\"{2}\"/>", ud.VirtualPath + m.Groups["image"].Value, style, alt);
                    }
                    else replacement = m.Groups["image"].Value;

                }
                else if (!string.IsNullOrEmpty(m.Groups["file"].Value))
                {
                    PageData pd = WikiManager.Instance.GetWikiArticle(pr);
                    UnifiedDirectory ud = pd.GetPageDirectory(false);
                    if (ud != null)
                    {
                        string tit = m.Groups["file"].Value;
                        if (!string.IsNullOrEmpty(m.Groups["filealt"].Value)) tit = m.Groups["filealt"].Value;
                        replacement = string.Format("<a href=\"{0}\">{1}</a>", ud.VirtualPath + m.Groups["file"].Value, tit);
                    }
                    else replacement = m.Groups["file"].Value; 
                }
                else if (!string.IsNullOrEmpty(m.Groups["redirect"].Value))
                {
                    PageReference target = WikiManager.Instance.FindWikiArticle(pr, m.Groups["redirect"].Value.ToLower());
                    if (target != PageReference.EmptyReference)
                    {
                        //Redirect
                        HttpContext.Current.Response.Redirect(DataFactory.Instance.GetPage(target).LinkURL, true);
                    }
                    else replacement = string.Empty;
                }
                else if (!string.IsNullOrEmpty(m.Groups["internal"].Value))
                {
                    //Internal wiki link
                    string link = HttpUtility.HtmlEncode(m.Groups["internal"].Value);
                    if (string.IsNullOrEmpty(title)) title = link;
                    else title = Parse(title, pr);

                    PageReference target = WikiManager.Instance.FindWikiArticle(pr, HttpUtility.HtmlDecode(link).ToLower());
                    string style = "";
                    if (target == PageReference.EmptyReference)
                    {
                        //Make Red Link
                        link = WikiManager.Instance.CreateNewArticleUrl(pr, HttpUtility.HtmlDecode(link));
                        style = "class=\"ArticleNew\"";
                    }
                    else link = WikiManager.GetFriendlyURL(target, DataFactory.Instance.GetPage(target).LinkURL);
                    replacement = "<A HREF=\"" + link + "\" " + style + ">" + title + "</A>";
                    if ((target == PageReference.EmptyReference) && (!WikiManager.Instance.GetWikiRoot(pr).QueryDistinctAccess(EPiServer.Security.AccessLevel.Create)))
                    {
                        //If link doesn't exist and current user doesn't have create permissions.
                        replacement = title;
                    }
                }
                else if (!string.IsNullOrEmpty(m.Groups["local"].Value))
                {
                    //Link locally on page
                    replacement = "<A HREF=\"#" + m.Groups["local"].Value + "\">" + m.Groups["local"].Value + "</A>";
                }
                else if (!string.IsNullOrEmpty(m.Groups["external"].Value))
                {
                    //External link
                    string link = m.Groups["external"].Value;
                    if (string.IsNullOrEmpty(title)) title = link;
                    replacement = "<A HREF=\"" + link + "\">" + title + "</A>";
                }
                else if (!string.IsNullOrEmpty(m.Groups["headcnt"].Value))
                {
                    //Heading
                    int hv = m.Groups["headcnt"].Value.Length;
                    replacement = "<H" + hv.ToString() + ">" + Parse(m.Groups["txt"].Value, pr) + "</H" + hv.ToString() + ">";
                }
                else if (!string.IsNullOrEmpty(m.Groups["stylecnt"].Value))
                {
                    //Bold or Italic
                    int hv = m.Groups["stylecnt"].Value.Length;
                    string style = "";

                    if (hv == 3) style = "font-weight:bold";
                    if (hv == 2) style = "font-style:italic";
                    if (style != "") replacement = "<span style=\"" + style + "\">" + Parse(m.Groups["txt"].Value, pr) + "</span> ";
                }
                if (replacement != null)
                {
                    txt=txt.Replace(m.Value, replacement, m.Index, m.Length);
                }
            }

        }

        public WikiParser()
        {
            ws = new WikiSyntax();
        }
    }
}
